package sys

import (
	"os"
	"fmt"
	"syscall"
	"os/signal"
	//"event/libs/signals"
	"runtime/debug"
	"encoding/json"
	"runtime"
	"time"
	"meman/sys/basic"
)

var debugFlag bool

//var exitSigSent bool
//
//func SysSignalHandle()  {
//	ss := signals.SignalSetNew()
//	handler := func(s os.Signal, arg interface{}) {
//		fmt.Printf("handle signal: %v\n", s)
//	}
//
//	ss.Register(syscall.SIGINT, handler)
//
//	for {
//		c := make(chan os.Signal)
//		var sigs []os.Signal
//		for sig := range ss.M  {
//			sigs = append(sigs, sig)
//		}
//		signal.Notify(c)
//		sig := <-c
//		err := ss.Handle(sig, nil)
//		if err != nil {
//			fmt.Printf("unknown signal received: %v\n", sig)
//			os.Exit(1)
//		}
//	}
//
//	// 系统信号监控通道
//	osSingalChan := make(chan os.Signal, 10)
//	signal.Notify(osSingalChan)
//
//
//	var sigusr = syscall.Signal(0xa)
//
//
//}
//
//
//func quitHandler () {
//	logger := Logger{}
//	if !exitSigSent {
//		logger.WriteMsg("info", "Quit signal received! exit...\n")
//		exitSigSent = true
//	} else {
//		logger.WriteMsg("info", "Quit signal already sent! ignore...\n")
//	}
//
//}
//
//func sigalrmHandler()  {
//	logger := Logger{}
//	logger.WriteMsg("info", "Received manual GC signal, starting free OS memory!")
//	gcStats := debug.GCStats{}
//	debug.ReadGCStats(&gcStats)
//	gcStatsOut, _ := json.MarshalIndent(gcStats, "", "")
//	fmt.Fprintf(os.Stdout, "%s\r\n", gcStatsOut)
//	debug.FreeOSMemory()
//}
//
//func sigusrHandler()  {
//	fmt.Printf("Current goroutines: %d\n", runtime.NumGoroutine())
//}
//
//func sighubHandler()  {
//	curDebugMode := !config.DebugEnabled()
//	logger := Logger{}
//	fmt.Sprintf()
//	logger.WriteMsg("info", fmt.Sprintf("Received force toggle DEBUG mode signal, setting DEBUG mode to : %v", curDebugMode))
//	config.SetDebug(curDebugMode)
//}


// 系统信号处理
func ProcessSysSignal() {
	var exitSigSent bool
	var exitSigSentLock = make(chan bool, 1)
	// 系统信号监控通道
	osSingalChan := make(chan os.Signal, 10)

	signal.Notify(osSingalChan)

	var sigusr1 = syscall.Signal(0xa)

	logger := basic.Logger{}

	// 在此阻塞，监控并处理系统信号
	for {
		osSingal := <-osSingalChan
		go func(sig *os.Signal) {
			switch *sig {
			case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
				exitSigSentLock <- true
				if !exitSigSent {
					logger.WriteMsg("info", "Quit signal received! exit...\n")
					exitSigSent = true
					<-exitSigSentLock
				} else {
					logger.WriteMsg("info","Quit signal already sent! ignore...\n")
					<-exitSigSentLock
					return
				}
				workerExitSigChan := make(chan string)
				//go localServer.Stop(&workerExitSigChan)
				//go msgredist.Stop(&workerExitSigChan)
				//go recoverwatcher.Stop(&workerExitSigChan)
				//go sender.Stop(&workerExitSigChan)
				sigReceivedCount := 0
				for sigReceivedCount < 4 {
					select {
					case workerName := <-workerExitSigChan:
						sigReceivedCount += 1
						logger.WriteMsg("info", fmt.Sprintf("%v worker exited.", workerName) )
					default:
						time.Sleep(time.Millisecond * 40)
					}
				}
				//exitSigChan <- int8(1)

			case syscall.SIGALRM:
				logger.WriteMsg("info", "Received manual GC signal, starting free OS memory!" )
				gcStats := debug.GCStats{}
				debug.ReadGCStats(&gcStats)
				gcStatsOut, _ := json.MarshalIndent(gcStats, "", "")
				fmt.Fprintf(os.Stdout, "%s\r\n", gcStatsOut)
				debug.FreeOSMemory()
			case sigusr1:
				fmt.Printf("Current goroutines: %d\n", runtime.NumGoroutine())
			// case syscall.SIGUSR2:
			// 	fmt.Printf("Configs: %s\n", config.GetConfig())
			case syscall.SIGHUP:
				curDebugMode := !DebugEnabled()
				logger.WriteMsg("info", fmt.Sprintf("Received force toggle DEBUG mode signal, setting DEBUG mode to : %v", curDebugMode) )
				SetDebug(curDebugMode)
			default:
				if DebugEnabled() {
					logger.WriteMsg("info", fmt.Sprintf("un-expected signal: %s(%d)\n", *sig, *sig))
				}
			}
		}(&osSingal)
	}
}




//	TODO: not coroutine safe
func DebugEnabled() bool {
	return debugFlag
}

//	TODO: not coroutine safe
func SetDebug(enable bool) {
	debugFlag = enable
}
